/*
	Written By Pradipna Nepal
	www.pradsprojects.com

	Copyright (C) 2012 Prads Projects
	Please read COPYING.txt included along with this source code for more detail.
	If not included, see http://www.gnu.org/licenses/
*/

#include "libFunctionTable.h"

//Populates function argument list
bool getArguments(const vector<Token> *tokens, FunctionEntry *entry);

bool FunctionTable::createFunctionTable(const vector<TokenModule> *modules, FuncTable *tOut) {
	FunctionEntry entry;

	entry.address = 0;
	for (unsigned int i = 1; i < modules->size(); ++i) {
		entry.name = (*modules)[i].name;
		entry.returnType = (*modules)[i].lines[0].tokens[0].getValue();
		if (!getArguments(&(*modules)[i].lines[0].tokens, &entry)) {
			return false;
		}
		tOut->insert(FuncTable::value_type(fnvHash(entry.name.c_str(), entry.name.size()), entry));
	}

	return true;
}

bool getArguments(const vector<Token> *tokens, FunctionEntry *entry) {
	entry->arguments.clear();

	if ((*tokens)[3].getToken() == TOKEN_CLOSEROUNDBRACKET) return true;	//No arguments
	
	string err;
	Arguments argument;

	for (unsigned int i = 3; i < tokens->size(); ++i) {
		if ((*tokens)[i].getDescription() == KW_VAR || ((*tokens)[i].getToken() == TOKEN_IDENTIFIER)) {
			argument.type = (*tokens)[i].getValue();
			++i;
			if ((*tokens)[i].getToken() == TOKEN_IDENTIFIER) {
				argument.name = (*tokens)[i++].getValue();
				entry->arguments.push_back(argument);
				if ((*tokens)[i].getToken() == TOKEN_COMMA) {
					continue;
				} else if ((*tokens)[i].getToken() == TOKEN_CLOSEROUNDBRACKET) {
					return true;
				} else {
					err = "In function declaration of: " + entry->name + ". Expected ',' or ')'...";
					printError(ERROR_SYNTAX, err.c_str());
					return false;
				}
			} else {
				err = "In function declaration of: " + entry->name + ". Expected identifier...";
				printError(ERROR_SYNTAX, err.c_str());
				return false;
			}
		} else {
			err = "In function declaration of: " + entry->name + ". Expected struct or var as type...";
			printError(ERROR_SYNTAX, err.c_str());
			return false;
		}
	}

	err = "In function declaration of: " + entry->name;
	printError(ERROR_SYNTAX, err.c_str());
	return false;
}